This invention relates generally to computer systems and more particularly to a method and apparatus for performing method lookup to support transitive method override in the presence of modularity constructs, such as packages.
Inheritance is a major property of most object oriented programming systems. With inheritance, when a class is declared as a subclass of a superclass, that subclass automatically inherits all of the methods and attributes of the superclass. Thus, if class A has method M1 and attribute AT1, then class B, which is a subclass of class A, automatically inherits method M1 and attribute AT1. In addition to inheriting the methods and attributes of the superclass, the subclass may further comprise additional methods and attributes. Thus, for the example given above, class B may further comprise methods M2 and M3, and attributes AT2 and AT3.
In addition to inheriting and adding methods and attributes, some object oriented systems further allow subclasses to override the methods of the superclass. That is, the subclass is allowed to provide an implementation for an inherited method which is different from that provided by the superclass. This means that, for the example given above, subclass B may provide a different implementation for method M1 than that provided by superclass A. For example, the implementation for M1 provided by superclass A may draw a square whereas the implementation for method M1 provided by subclass B draws a circle. Thus, even though both methods have the same name, they may have different implementations. Which implementation is invoked depends upon the class of the object instance on which the method is invoked. If the method is invoked on a class A instance, then the implementation provided by class A will be invoked. If the method is invoked on a class B instance, then the implementation provided by class B will be invoked. Because there may be multiple implementations for any particular method, a determination will have to be made at runtime as to which implementation to invoke. The process of selecting which implementation to invoke at runtime is referred to as dynamic method dispatch.
In single inheritance systems where every subclass is able to access, and hence, override every method of a higher level class, the dynamic method dispatch process is relatively straightforward. However, some systems, such as the Java(trademark) programming system manufactured by Sun Microsystems, Inc. of Mountain View, Calif., implement constructs known as xe2x80x9cmodularity constructsxe2x80x9d which make it possible for a developer to restrict the accessibility of certain methods of certain classes to other classes. In the face of these accessibility restrictions, dynamic method dispatch is made much more complicated.
To elaborate, a modularity construct, sometimes referred to as a xe2x80x9cpackagexe2x80x9d in Java(trademark), provides a mechanism for grouping or encapsulating selected classes. The package construct makes it possible to limit access to the classes within a package by classes in other packages. More specifically, each method of each class within a package may be declared as xe2x80x9cpublicxe2x80x9d, xe2x80x9cprotectedxe2x80x9d, or xe2x80x9cpackage privatexe2x80x9d. If a method is declared public or protected (denoted as public/protected hereinafter), then it may be accessed, and hence overridden, by any subclass of that class. On the other hand, if a method is declared package private, then that method may be accessed and overridden by a subclass if and only if that subclass is within the same package. Subclasses outside the package may not access or override the method. FIG. 1 illustrates an example of such a situation. In FIG. 1, there is shown two packages, P1 and P2. Package P1 contains a class A having a package private method M1. Package P2 contains a class B which extends A (meaning that B is a subclass of A) having a public/protected method M1. Because method M1 of class A is declared package private, and because class B is not in the same package as class A, class B will not be able to access or to override the method M1 of class A. Note that the package construct does not prevent class B from being a subclass of A, and hence, inheriting all of the attributes and methods of class A. The package only prevents class B from overriding the method M1 of class A. To enforce package constraints, it is a general rule that unless a subclass is within the same package as a higher level class that it wishes to override, it cannot override a package private method of the higher level class.
While on the surface, this general rule appears to effectively enforce the accessibility constraints imposed by modularity constructs, it can lead to some undesirable results, one of which is that of non-transitive method override. To illustrate how this non-transitive result can arise, suppose that a structure such as that shown in FIG. 2 is created, wherein there are two packages, P1 and P2. In package P1, there is a class A having a package private method M1. In the same package, there is a subclass B which extends A, having a public/protected method M1. In package P2, there is a subclass C which extends B, and which has a public/protected method M1. With such a structure, it is clear that method M1 of subclass B can access and hence override method M1 of class A (since B is in the same package as A). It is also clear that method M1 of class C can override the method M1 of class B (since method M1 of B is declared to be public/protected). According to the transitive property, if method M1 of C can override method M1 of B, and method M1 of B can override method M1 of A, then method M1 of C should be able to override method M1 of A. This is not the result in this example, however, because under the rule set forth above, M1 of C cannot override M1 of A because M1 of A is package private and C is not in the same package as A. Thus, as this example shows, strict adherence to this rule can lead to non-transitive results. Because this is a somewhat non-intuitive result, and because transitive method override is a desirable property, there is a need for an improved dynamic method dispatch mechanism which is both capable of enforcing the accessibility constraints of modular constructs and providing transitive method override.
One mechanism that may be used to perform dynamic method dispatch is a method lookup mechanism. In the present invention, there is provided an improved method lookup mechanism which not only enforces accessibility constraints imposed by modularity constructs but also enables transitive method override.
According to one embodiment of the present invention, when a method m is invoked on a target object, the method m in a resolved class is checked to determine whether it has been declared as public/protected. If so, then standard method lookup may be used to determine the proper implementation of method m to invoke. However, if the resolved method is not declared as public/protected, then the class of the target object is searched for an implementation of the method m. If no implementation is found, then a superclass of the target object class is searched for an implementation. This process repeats until an implementation is found or until the resolved class is reached.
If an implementation for method m is found in a class (referred to as the current class) other than the resolved class, then a determination is made as to whether the current class can access the method m in the resolved class. The current class can access method m of the resolved class if the current class is in the same package P as the resolved class, or if an intervening class has xe2x80x9cpublicizedxe2x80x9d the method m of the resolved class. If either one of these conditions is met, then the implementation for method m in the current class is invoked. In effect, the method m of the current class is allowed to override the method m of the resolved class. By performing method lookup in accordance with the present invention, it is possible to both enforce accessibility constraints imposed by modularity constructs and enable transitive method override.